package cn.ycc1.baseset.exceptions;

/**
 * Throwing Exceptions
 * @author ycc
 * @date 2025/3/6
 */
public class ThrowingExceptions {
    /**
     * Specifying the Exceptions Thrown by a Method
     * The previous section showed how to write an exception handler for the writeList() method in the ListOfNumbers class.
     * Sometimes, it's appropriate for code to catch exceptions that can occur within it. In other cases, however,
     * it's better to let a method further up the call stack handle the exception. For example, if you were providing the
     * ListOfNumbers class as part of a package of classes, you probably couldn't anticipate the needs of all the users of your
     * package. In this case, it's better to not catch the exception and to allow a method further up the call stack to handle it.
     *
     * If the writeList() method doesn't catch the checked exceptions that can occur within it, the writeList() method must
     * specify that it can throw these exceptions. Let's modify the original writeList() method to specify the exceptions it
     * can throw instead of catching them. To remind you, here's the original version of the writeList() method that
     * won't compile.
     *
     * public void writeList() {
     *     PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));
     *     for (int i = 0; i < SIZE; i++) {
     *         out.println("Value at: " + i + " = " + list.get(i));
     *     }
     *     out.close();
     * }
     * To specify that writeList() can throw two exceptions, add a throws clause to the method declaration for the writeList()
     * method. The throws clause comprises the throws keyword followed by a comma-separated list of all the exceptions thrown
     * by that method. The clause goes after the method name and argument list and before the brace that defines the scope of
     * the method; here's an example.
     *
     * public void writeList() throws IOException, IndexOutOfBoundsException {
     * Remember that IndexOutOfBoundsException is an unchecked exception; including it in the throws clause is not mandatory.
     * You could just write the following.
     *
     * public void writeList() throws IOException {
     */

    /**
     * How to Throw Exceptions
     * Before you can catch an exception, some code somewhere must throw one. Any code can throw an exception: your code,
     * code from a package written by someone else such as the packages that come with the Java platform, or the Java runtime
     * environment. Regardless of what throws the exception, it's always thrown with the throw statement.
     *
     * As you have probably noticed, the Java platform provides numerous exception classes. All the classes are descendants
     * of the Throwable class, and all allow programs to differentiate among the various types of exceptions that can occur
     * during the execution of a program.
     *
     * You can also create your own exception classes to represent problems that can occur within the classes you write.
     * In fact, if you are a package developer, you might have to create your own set of exception classes to allow users to
     * differentiate an error that can occur in your package from errors that occur in the Java platform or other packages.
     *
     * You can also create chained exceptions. For more information, see the Chained Exceptions section.
     */

    /**
     * The Throw Statement
     * All methods use the throw statement to throw an exception. The throw statement requires a single argument: a throwable
     * object. Throwable objects are instances of any subclass of the Throwable class. Here's an example of a throw statement.
     *
     * throw someThrowableObject;
     * Let's look at the throw statement in context. The following pop() method is taken from a class that implements a common
     * stack object. The method removes the top element from the stack and returns the object.
     *
     * public Object pop() {
     *     Object obj;
     *
     *     if (size == 0) {
     *         throw new EmptyStackException();
     *     }
     *
     *     obj = objectAt(size - 1);
     *     setObjectAt(size - 1, null);
     *     size--;
     *     return obj;
     * }
     * The pop() method checks to see whether any elements are on the stack. If the stack is empty (its size is equal to 0),
     * pop instantiates a new EmptyStackException object, a member of java.util and throws it. The Creating Exception Classes
     * section in this chapter explains how to create your own exception classes. For now, all you need to remember is that
     * you can throw only objects that inherit from the java.lang.Throwable class.
     *
     * Note that the declaration of the pop() method does not contain a throws clause. EmptyStackException is not a checked
     * exception, so pop is not required to state that it might occur.
     */

    /**
     * Throwable Class and Its Subclasses
     * The objects that inherit from the Throwable class include direct descendants (objects that inherit directly from
     * the Throwable class) and indirect descendants (objects that inherit from children or grandchildren of the Throwable class).
     * The figure below illustrates the class hierarchy of the Throwable class and its most significant subclasses.
     * As you can see, Throwable has two direct descendants: Error and Exception.
     */

    /**
     * Error Class
     * When a dynamic linking failure or other hard failure in the Java virtual machine occurs, the virtual machine throws
     * an Error. Simple programs typically do not catch or throw instances of Error.
     */

    /**
     * Exception Class
     * Most programs throw and catch objects that derive from the Exception class. An Exception indicates that a problem
     * occurred, but it is not a serious system problem. Most programs you write will throw and catch instances of Exception
     * as opposed to Error.
     *
     * The Java platform defines the many descendants of the Exception class. These descendants indicate various types of
     * exceptions that can occur. For example, IllegalAccessException signals that a particular method could not be found,
     * and NegativeArraySizeException indicates that a program attempted to create an array with a negative size.
     *
     * One Exception subclass, RuntimeException, is reserved for exceptions that indicate incorrect use of an API.
     * An example of a runtime exception is NullPointerException, which occurs when a method tries to access a member of
     * an object through a null reference. The section Unchecked Exceptions — The Controversy discusses why most applications
     * shouldn't throw runtime exceptions or subclass RuntimeException.
     */

    /**
     * Chained Exceptions
     * An application often responds to an exception by throwing another exception. In effect, the first exception causes the
     * second exception. It can be very helpful to know when one exception causes another. Chained Exceptions help the
     * programmer do this.
     *
     * The following are the methods and constructors in Throwable that support chained exceptions.
     *
     * Throwable getCause()
     * Throwable initCause(Throwable)
     * Throwable(String, Throwable)
     * Throwable(Throwable)
     * The Throwable argument to initCause() and the Throwable constructors is the exception that caused the current exception.
     * getCause() returns the exception that caused the current exception, and initCause() sets the current exception's cause.
     *
     * The following example shows how to use a chained exception.
     *
     * try {
     *
     * } catch (IOException e) {
     *     throw new SampleException("Other IOException", e);
     * }
     * In this example, when an IOException is caught, a new SampleException exception is created with the original cause
     * attached and the chain of exceptions is thrown up to the next higher level exception handler.
     */

    /**
     * Accessing Stack Trace Information
     * Now let's suppose that the higher-level exception handler wants to dump the stack trace in its own format.
     *
     * Definition: A stack trace provides information on the execution history of the current thread and lists the names of
     * the classes and methods that were called at the point when the exception occurred. A stack trace is a useful debugging
     * tool that you'll normally take advantage of when an exception has been thrown.
     *
     * The following code shows how to call the getStackTrace() method on the exception object.
     *
     * catch (Exception cause) {
     *     StackTraceElement elements[] = cause.getStackTrace();
     *     for (int i = 0, n = elements.length; i < n; i++) {
     *         System.err.println(elements[i].getFileName()
     *             + ":" + elements[i].getLineNumber()
     *             + ">> "
     *             + elements[i].getMethodName() + "()");
     *     }
     * }
     */

    /**
     * Logging API
     * The next code snippet logs where an exception occurred from within the catch block. However, rather than manually
     * parsing the stack trace and sending the output to java.util.logging, it sends the output to a file using the logging
     * facility in the java.util.logging package.
     *
     * try {
     *     Handler handler = new FileHandler("OutFile.log");
     *     Logger.getLogger("").addHandler(handler);
     *
     * } catch (IOException e) {
     *     Logger logger = Logger.getLogger("package.name");
     *     StackTraceElement elements[] = e.getStackTrace();
     *     for (int i = 0, n = elements.length; i < n; i++) {
     *         logger.log(Level.WARNING, elements[i].getMethodName());
     *     }
     * }
     */

    /**
     * Creating Exception Classes
     * When faced with choosing the type of exception to throw, you can either use one written by someone else — the Java
     * platform provides a lot of exception classes you can use — or you can write one of your own. You should write your
     * own exception classes if you answer yes to any of the following questions; otherwise, you can probably use
     * someone else's.
     *
     * Do you need an exception type that isn't represented by those in the Java platform?
     * Would it help users if they could differentiate your exceptions from those thrown by classes written by other vendors?
     * Does your code throw more than one related exception?
     * If you use someone else's exceptions, will users have access to those exceptions? A similar question is, should your
     * package be independent and self-contained?
     * An Example
     * Suppose you are writing a linked list class. The class supports the following methods, among others:
     *
     * objectAt(int n) — Returns the object in the nth position in the list. Throws an exception if the argument is less than
     * 0 or more than the number of objects currently in the list.
     * firstObject() — Returns the first object in the list. Throws an exception if the list contains no objects.
     * indexOf(Object o) — Searches the list for the specified Object and returns its position in the list. Throws an exception
     * if the object passed into the method is not in the list.
     * The linked list class can throw multiple exceptions, and it would be convenient to be able to catch all exceptions thrown
     * by the linked list with one exception handler. Also, if you plan to distribute your linked list in a package,
     * all related code should be packaged together. Thus, the linked list should provide its own set of exception classes.
     *
     * The next figure illustrates one possible class hierarchy for the exceptions thrown by the linked list.
     */

    /**
     * Any Exception subclass can be used as the parent class of LinkedListException. However, a quick perusal of those
     * subclasses shows that they are inappropriate because they are either too specialized or completely unrelated to
     * LinkedListException. Therefore, the parent class of LinkedListException should be Exception.
     *
     * Most applications you write will throw objects that are instances of Exception. Instances of Error are normally used
     * for serious, hard errors in the system, such as those that prevent the JVM from running.
     *
     * Note: For readable code, it's good practice to append the string Exception to the names of all classes that inherit
     * (directly or indirectly) from the Exception class.
     */
}
